package mouseBehaviors;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.Enumeration;

import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnBehaviorPost;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
import com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback;
import com.sun.j3d.utils.behaviors.mouse.MouseWheelZoom;

public class MyMouseZoomscale extends MouseBehavior {

    double zoom_factor = 1.1;
    
  
    private MouseBehaviorCallback callback = null;

    /**
     * Creates a zoomscale behavior given the transform group.
     * @param transformGroup The transformGroup to operate on.
     */
    public MyMouseZoomscale(TransformGroup transformGroup) {
    	super(transformGroup);
    }

    /**
     * Creates a default mouse zoomscale behavior.
     **/
    public MyMouseZoomscale(){
    	super(0);
    }

    /**
     * Creates a zoomscale behavior.
     * Note that this behavior still needs a transform
     * group to work on (use setTransformGroup(tg)) and
     * the transform group must add this behavior.
     * @param flags
     */
    public MyMouseZoomscale(int flags) {
    	super(flags);
    }

    /**
     * Creates a zoomscale behavior that uses AWT listeners and behavior
     * posts rather than WakeupOnAWTEvent.  The behavior is added to the
     * specified Component.  A null component can be passed to specify
     * the behavior should use listeners.  Components can then be added
     * to the behavior with the addListener(Component c) method.
     * @param c The Component to add the MouseListener
     * and MouseMotionListener to.
     * @since Java 3D 1.2.1
     */
    public MyMouseZoomscale(Component c) {
    	super(c, 0);
    }

    /**
     * Creates a zoomscale behavior that uses AWT listeners and behavior
     * posts rather than WakeupOnAWTEvent.  The behaviors is added to
     * the specified Component and works on the given TransformGroup.
     * @param c The Component to add the MouseListener and
     * MouseMotionListener to.  A null component can be passed to specify
     * the behavior should use listeners.  Components can then be added
     * to the behavior with the addListener(Component c) method.
     * @param transformGroup The TransformGroup to operate on.
     * @since Java 3D 1.2.1
     */
    public MyMouseZoomscale(Component c, TransformGroup transformGroup) {
    	super(c, transformGroup);
    }

    /**
     * Creates a zoomscale behavior that uses AWT listeners and behavior
     * posts rather than WakeupOnAWTEvent.  The behavior is added to the
     * specified Component.  A null component can be passed to specify
     * the behavior should use listeners.  Components can then be added
     * to the behavior with the addListener(Component c) method.
     * Note that this behavior still needs a transform
     * group to work on (use setTransformGroup(tg)) and the transform
     * group must add this behavior.
     * @param flags interesting flags (wakeup conditions).
     * @since Java 3D 1.2.1
     */
    public MyMouseZoomscale(Component c, int flags) {
    	super(c, flags);
    }

    public void initialize() {
		super.initialize();
		
    }

    
	@Override
	public void processStimulus(Enumeration criteria) {
		// TODO Auto-generated method stub
		WakeupCriterion wakeup;
		AWTEvent[] events;
	 	MouseEvent evt;
	    
		while (criteria.hasMoreElements()) {
		    wakeup = (WakeupCriterion) criteria.nextElement();
		    if (wakeup instanceof WakeupOnAWTEvent) {
		    	events = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
				if (events.length > 0) {
				    evt = (MouseEvent) events[events.length-1];
				    doProcess(evt);
				}
		    }

		    else if (wakeup instanceof WakeupOnBehaviorPost) {
		    	while (true) {
				    synchronized (mouseq) {
						if (mouseq.isEmpty()) break;
						evt = (MouseEvent)mouseq.remove(0);
						// consolodate MOUSE_DRAG events
						while((evt.getID() == MouseEvent.MOUSE_PRESSED) && !mouseq.isEmpty() && 
								(((MouseEvent)mouseq.get(0)).getID() ==  MouseEvent.MOUSE_DRAGGED)) {
						    	evt = (MouseEvent)mouseq.remove(0);
						}
				    }
				    doProcess(evt);
		    	}
		   }
		    
		}
		wakeupOn (mouseCriterion);
	}
	
	
	
	 void doProcess(MouseEvent evt) {
			int id;
			int units = 0;

			processMouseEvent(evt);
			
			if (((buttonPress)&&((flags & MANUAL_WAKEUP) == 0)) ||
			    ((wakeUp)&&((flags & MANUAL_WAKEUP) != 0))){
			    id = evt.getID();
			    if ((id == MouseEvent.MOUSE_WHEEL) && !evt.isAltDown() && !evt.isMetaDown()){
			    	MouseWheelEvent wheelEvent = (MouseWheelEvent)evt;
			    	if (wheelEvent.getScrollType() == wheelEvent.WHEEL_UNIT_SCROLL ) {
			    		units = wheelEvent.getUnitsToScroll();
			    		//int count = wheelEvent.getScrollAmount();
			    		//System.out.println(units+"*************************");
			    		//System.out.println(count+"*************************");
			    		//System.out.println("=============================");
			    		Transform3D transform3d = new Transform3D();
			    		transformGroup.getTransform(transform3d);
			    		double scale = transform3d.getScale();
			    		if(units>0){
			    			scale *= zoom_factor;
			    		}
			    		else {
							scale /= zoom_factor;
						}
			    		transform3d.setScale(scale);
			    		transformGroup.setTransform(transform3d);
			    	} 
			    	
			    }
		    }
	 }
	 
	 public void transformChanged( Transform3D transform ) {
	 }
	 
	 public void setupCallback( MouseBehaviorCallback callback ) {
			this.callback = callback;
	 }
}
